package cl.orangepeople.whyem.portal.backend.api.utils;

import java.io.Serializable;
import java.text.DecimalFormat;
import java.text.DecimalFormatSymbols;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.regexp.RE;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class FormatterUtils implements Serializable {
    public final static String DEFAULT_RUT_PATTERN = "##.###.###-X";
    private static RE outRutRE = new RE("([0\\#\\.\\,]+)([^X^x^\\,^\\.^9]*)([Xx]*)");
    private static RE inRutRE = new RE("([0-9\\.]+)\\-([a-zA-Z0-9]+)");
    private static Logger logger = LoggerFactory.getLogger(FormatterUtils.class);
    private boolean ignorarRUTVacio = false;

    public FormatterUtils() {
	this(false);
    }

    public FormatterUtils(boolean ignorarRUTVacio) {
        this.ignorarRUTVacio = ignorarRUTVacio;
    }

    public static Integer parseRut(String value) {
        Integer result = null;
        if (value != null) {
            // Borramos los caracteres esperables
            String rut = StringUtils.remove(value, ".");
            rut = StringUtils.remove(rut, ",");
            rut = StringUtils.remove(rut, "-");
            // Separamos el numero y el digito verificador
            if (!StringUtils.isEmpty(rut) && rut.length() > 1 && rut.length() < 11) {
                String numRut = rut.substring(0, rut.length() - 1);
                String dv = rut.substring(rut.length() - 1).toUpperCase();
                if (NumberUtils.isDigits(numRut)) {
                    int intRut = Integer.parseInt(numRut);
                    if (dv.charAt(0) == getDV(intRut)) {
                        result = new Integer(intRut);
                    }
                }
            }
        }
        return result;
    }

    public static String formatRut(Number o) throws Exception {
        String pattern = DEFAULT_RUT_PATTERN;
        String formatedCheck = StringUtils.EMPTY;
        Number rut = (Number) o;
        if (rut != null) {
            String value = rut + "-" + getDV(rut.intValue());
            if (!(outRutRE.match(pattern))) {
                logger.debug("Pattern incorrecto : " + pattern);
            }
            if (!(inRutRE.match(value))) {
                throw new Exception("Formato de entrada incorrecto:"
                        + rut);
            }
            String checkFmt = outRutRE.getParen(1);
            String valueCheck = inRutRE.getParen(1);
            DecimalFormatSymbols dfs = new DecimalFormatSymbols();
            int indexGroupChar = checkFmt.indexOf(".") >= 0 ? checkFmt.indexOf(".") : checkFmt.indexOf(",");
            if (indexGroupChar >= 0) {
                dfs.setGroupingSeparator(checkFmt.charAt(indexGroupChar));
            }
            DecimalFormat df = null;
            if (indexGroupChar >= 0) {
                df = new DecimalFormat(checkFmt.replace(
                        checkFmt.charAt(indexGroupChar), ','), dfs);
            } else {
                df = new DecimalFormat(checkFmt, dfs);
            }
            df.setGroupingUsed(indexGroupChar >= 0);
            formatedCheck = df.format(Long.parseLong(valueCheck));
            String separator = outRutRE.getParen(2);
            if (!StringUtils.isEmpty(separator)) {
                formatedCheck = formatedCheck + separator;
            }
            String dv = outRutRE.getParen(3);
            if (!StringUtils.isEmpty(dv)) {
                formatedCheck = formatedCheck + inRutRE.getParen(2);
            }
        }
        return formatedCheck;
    }
    
    public static Integer getRutWithVerifierDigit(Integer rut){
    	StringBuffer buffer = new StringBuffer();
    	buffer.append(rut);
    	buffer.append(FormatterUtils.getDV(rut));
    	
    	return Integer.parseInt(buffer.toString());
    }
    
    public static String getRutWithVerifierDigit(String rut){
    	StringBuffer buffer = new StringBuffer();
    	buffer.append(rut);
    	buffer.append(FormatterUtils.getDV(Integer.parseInt(rut)));
    	
    	return buffer.toString();
    }

    public static char getDV(int rut) {
        int M = 0, S = 1, T = rut;
        for (; T != 0; T /= 10) {
            S = (S + T % 10 * (9 - M++ % 6)) % 11;
        }
        return (char) (S != 0 ? S + 47 : 75);
    }
}